Michael Rudolph
THEORETICAL PHYSICS • DISCRETE MATHEMATICS
ChessY: A Mathematica toolbox for the generation,
visualization and analysis of positional chess graphs


M. Rudolph-Lilith

SoftwareX, 2019, in press

Abstract

The game of chess is undoubtedly one of the most popular two-player strategy board games in history, enjoyed by casual players and competing celebrated professionals alike, and serves as prototype research subject in a vast variety of fields. Although a plethora of parsers on a large number of different platforms is readily available for processing records of chess games provided in online databases, Mathematica remains, somewhat surprisingly, exempt. ChessY attempts to fill this gap, by providing a simple set of tools for handling Portable Game Notation (PGN) chess records and their translation into positional chess graphs, thus opening the door for a systematic analysis of chess games within the powerful confines of graph theory using Mathematica.

Supplementary Information and Material

The ChessY toolbox (v1.0) for Mathematica (v10.0 or above) can be downloaded here. Files include:

ChessY.m ChessY toolbox (v1.0)
README.txt ChessY manual
example*.pgn example PGN records used in the manual
pieces/* directory with vector graphics of chess pieces

Please note that ChessY is in active development. Feel free to contact me for general feedback and comments, bug fixes, problems as well as feature requests and suggestions.

Manual


Data Objects, Constants and Auxiliary Functions

ChessY is build around three principal types of data objects: position, nodes and edges. While the position object contains a list of pieces and their location on the chessboard, thus uniquely encodes a given chess position, nodes and edges are lists which characterize the chess graph associated with a given position.

Position Data Object

The position data object is a Mathematica list containing two elements:

position = { SUPPLEMENTARY_INFO , LIST_OF_OCCUPIED_SQUARES }

Here, SUPPLEMENTARY_INFO is a key-value association list containing supplementary information which characterize a given chess position. This association list has the form

SUPPLEMENTARY_INFO = <| "enpassant"->VALUE ,
                        "castling"->VALUE ,
                        "check"->VALUE ,
                        "checkmate"->VALUE |>

where:

The LIST_OF_OCCUPIED_SQUARES entry is a list of elements of type

LIST_OF_OCCUPIED_SQUARES = { { nodeID , pieceID } , { nodeID , pieceID } , ... }

containing the set of all occupied squares or nodes. Here, nodeID is a unique identifier of each chessboard square, ranging from 1 to 64, starting in the lower left-hand corner with the $a1$ square and ending in the upper right-hand corner ($h8$ square). That is,


file/rank nodeID
$a1$1
$b1$2
......
$h1$8
$a2$9
......
$g8$63
$h8$64

Table 1
file/rank-node ID mapping
utilized in ChessY

For mapping the file/rank chessboard square identifier to the nodeID, see File/Rank-NodeID Mapping.

The pieceID is a unique identifier for the chess piece type:

chess piece pieceID
white king-2
white queen-3
white rook-4
white bishop-5
white knight-6
white pawn-7
black king2
black queen3
black rook4
black bishop5
black knight6
black pawn7
none0
Table 2
Chess piece identification utilized in ChessY

EXAMPLES:

empty chess board:

positionEmpty =
{
  <| "enpassant"->0,
     "castling"->{{True,True},{True,True}},
     "check"->False,
     "checkmate"->False |>,
  {}
};

initial chess position:

positionStart =
{
  <| "enpassant"->0,
     "castling"->{{True,True},{True,True}},
     "check"->False,
     "checkmate"->False |>,
  {
     {1,wR},{2,wN},{3,wB},{4,wQ},{5,wK},{6,wB},{7,wN},{8,wR},
     {9,wP},{10,wP},{11,wP},{12,wP},{13,wP},{14,wP},{15,wP},{16,wP},
     {49,bP},{50,bP},{51,bP},{52,bP},{53,bP},{54,bP},{55,bP},{56,bP},
     {57,bR},{58,bN},{59,bB},{60,bQ},{61,bK},{62,bB},{63,bN},{64,bR}
  }
};

position of move 11 in match Spassky-Fischer during the 8th World Championship on Jul 16, 1972:

position23SpasskyFischer1972 =
{
  <| "enpassant"->0,
     "castling"->{{False,False},{False,False}},
     "check"->False,
     "checkmate"->False |>,
  {
    {1,wR},{3,wB},{6,wR},{7,wK},{9,wP},{10,wP},{11,wQ},{12,wN},
    {13,wB},{14,wP},{15,wP},{16,wP},{19,wN},{29,wP},{35,bP},{36,wP},
    {40,bN},{44,bP},{47,bP},{49,bP},{50,bP},{52,bN},{54,bP},{55,bB},
    {56,bP},{57,bR},{59,bB},{60,bQ},{61,bR},{63,bK}
  }
};

Nodes Data Object

The nodes data object

nodes = { NODE_STATE , NODE_STATE , ... }

is a 1-dimensional list (vector) of length 64 with element $i$ containing the node state of node $i$. The NODE_STATE value characterizes each node, and can take various values depending on an optional argument State which can be chosen in many functions of ChessY (see below). Specifically,

Edges Data Object

The edges data object

edges = { EDGE , EDGE , ... }

is a 2-dimensional list (matrix), specifically a variable-length list with elements of the form

EDGE = { SOURCE_NODE_ID , TARGET_NODE_ID , EDGE_STATE }

where the edge EDGE_STATE is equal to the color state of the source node (Table 3).

File/Rank-NodeID Mapping

Each square on the chessboard is uniquely labelled in terms of file (a,b,...,h) and rank (1,2,...,8). In order to simplify the mapping between file/rank and node ID (Table 1), ChessY associates each file with numbers: $a \rightarrow 1$, $b \rightarrow 2$, ..., $h \rightarrow 8$. For converting between file, rank and node IDs, ChessY provides three functions:

node ID $\rightarrow$ file:

file[ NODE_ID ]

node ID $\rightarrow$ rank:

rank[ NODE_ID ]

file/rank $\rightarrow$ node ID:

node[ FILE , RANK ]

Moves

In order to generate positional chess graphs from given chess positions, Chessy employs 2-dimensional data arrays which effectively encode all possible moves for each type of chess piece:

Visualization

Additional graphical objects are required to visualize a given chess position in the classical style. These objects are imported as EPS files residing in the subdirectory pieces/.

Chess Position Generation

ChessY provides two ways to generate chess positions, a manual one and by parsing PGN chess records.

Manual Generation

ChessY has two functions for populating a chess board manually with chess pieces, thus creating valid chess positions. Using the function

getPositionFromPieceFileRank[ { p1 , p2 , ... } ]

pieces p1, p2, ... can be placed on the board by specifying the piece color and type, as well as the file and rank of the target square. Entries in the argument list must be of the form

p* = COLOR/TYPE/FILE/RANK

The function takes optional arguments:

EXAMPLES:

identification of white queen on square $a1$:

wQa1

chess position with a white queen on $c5$ and a black king on $e8$:

position = getPositionFromPieceFileRank[ {wQc5,bKe8} ];

ply 29 in Pietzcker Christmas Tournament (1928) between Gundersen and Faul:

position = getPositionFromPieceFileRank[
             {
               wRa1,wBc1,wKe1,wRh1,wPa2,wPb2,wPf2,wPg2,wNc3,
               wQg4,wPe5,wPh5,wNe6,bRa8,bBc8,bQd8,bRf8,bPa7,
               bPb7,bNe7,bKh6,bPd5,bPf5,bPg5,bBb4,bNd4
             },
             EnPassant->g6,
             Castling->{{True,True},{False,False}},
             Check->False,
             Checkmate->False
           ];

The function

getPositionFromPieceNode[ { p1 , p2 , ... } ]

generates a position by populating a chess graph's nodes with pieces p1, p2 identified by

p* = COLOR/TYPE/NODE_ID

where NODE_ID ranges from 1 to 64 (see Position Data Object). Optional arguments are the same as for getPositionFromPieceFileRank[], except that the value of the EnPassant option is a node ID.

EXAMPLES:

identification of white queen on square $a1$:

wQ1

chess position with a white queen on node 35 ($c5$) and a black king on node 61 ($e8$):

position = getPositionFromPieceNode[ {wQ35,bK61} ];

ply 29 in Pietzcker Christmas Tournament (1928) between Gundersen and Faul:

position = getPositionFromPieceNode[
             {
               wR1,wB3,wK5,wR8,wP9,wP10,wP14,wP15,wN19,wQ31,
               wP37,wP40,wN45,bR57,bB59,bQ60,bR62,bP49,bP50,
               bN53,bK48,bP36,bP38,bP39,bB26,bN28
             },
             EnPassant->g6,
             Castling->{{True,True},{False,False}},
             Check->False,
             Checkmate->False
           ];

PGN Parser

The second way to generate chess positions is to utilize ChessY's PGN parser, which processes PGN-formatted chess game records. Two functions are available, with the first being (internally) used to get specific information of the move from a single PGN-formatted string, and the second for parsing a whole PGN game record. Only the latter returns a list of chess positions.

The function

parsePGNMove[ MOVE ]

parses a single PGN compliant chessmove string and returns a list with details of the move. Please note that this is a very baseline parser for PNG-formatted strings which might not cover deviations from the SAN format recommended by FISA as well as special cases. This function is merely employed for internal purposes, so use with care!

The function returns a list with 11 elements

{
  PIECE , FILE , RANK , CAPTURE , DISAMBIGUATION , CASTLING ,
  ENPASSANT , PROMOTION , CHECK , CHECKMATE , RESULT
}

where: